package concurrent.executors;

import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import utils.Log;

public class ThreadPoolTest {

  /**
   * newCachedThreadPool: 创建可缓存的线程池，如果线程池中的线程在60秒未被使用就将被移除，在执行新的任务时，
   * 当线程池中有之前创建的可用线程就重用可用线程，否则就新建一条线程
   *
   * @param args
   * @throws InterruptedException
   *
   * 输出：（为每个任务新建一条线程，共创建了3条线程）
   * 线程名字： pool-1-thread-1 任务名为： 1
   * 线程名字： pool-1-thread-2 任务名为： 2
   * 线程名字： pool-1-thread-3 任务名为： 3
   * 去掉注释其输出如下：（始终重复利用一条线程，因为newCachedThreadPool能重用可用线程）
   * 线程名字： pool-1-thread-1 任务名为： 1
   * 线程名字： pool-1-thread-1 任务名为： 2
   * 线程名字： pool-1-thread-1 任务名为： 3
   *
   */
  public static void main(String[] args) throws InterruptedException {
    if (true) {
      testSinglePool();
      return;
    }

    ExecutorService threadPool = Executors.newCachedThreadPool();//线程池里面的线程数会动态变化，并可在线程线被移除前重用
    for (int i = 1; i <= 3; i++) {
      final int task = i;   //10个任务
      TimeUnit.SECONDS.sleep(1);
      threadPool.execute(new Runnable() {    //接受一个Runnable实例
        public void run() {
          System.out.println("线程名字： " + Thread.currentThread().getName() + "  任务名为： " + task);
        }
      });
    }
  }

  static int task = 1;
  static ExecutorService producePool = Executors.newSingleThreadExecutor();
  static ExecutorService consumerPool = Executors.newFixedThreadPool(6);
  static void testSinglePool() {
    for (int i = 0; i < 5; i++) {
      producePool.submit(new worker());
      consumerPool.submit(new consumer());
    }
  }

  static class worker implements Runnable {

    @Override
    public void run() {
      ++task;
      Log.vn("======>worker： " + Thread.currentThread().getName() + "  task： " + task);
      sleepRandom();

      producePool.submit(this);
    }
  }

  static class consumer implements Runnable {

    @Override
    public void run() {
      Log.vn("consumer： " + Thread.currentThread().getName() + "  task： " + task);
      sleepRandom();

      consumerPool.submit(this);
    }
  }

  static void sleepRandom() {
    try {
      int mills = new Random().nextInt(5000);
      // Log.vn("sleepRandom, mills:" + mills);
      Thread.sleep(mills);
    } catch (InterruptedException ie) {
      ie.printStackTrace();
    }
  }

}
